#ifndef ILRT_TYPE_H_
#define ILRT_TYPE_H_

#include <illib/Allocator.h>
#include <illib/Vector.h>

namespace ilrt{
	class BasicTypedPointer;
	class BasicPointer;
	class String;
	class Runtime;
	class BasicType;
	class BasicType : public illib::BasicLinkedList::Node{
	public:
		BasicType(Runtime & runtime){

		}
		virtual ~BasicType();
		virtual BasicTypedPointer _create() = 0;
		virtual void _destroy(BasicPointer value) = 0;
		virtual const char * name() = 0;
	};
	class TypedBasicPointer;
	class BasicPointer{
	protected:
		static char reserved_[256+256+4];
		void * value_;
	public:
		void * _value(){
			return value_;
		}
		BasicPointer();
		BasicPointer(void * value);
		BasicPointer(const BasicPointer &value);
		BasicPointer(const TypedBasicPointer &value);
		BasicPointer & operator=(const BasicPointer &rhs){
			value_ = rhs.value_;
			return *this;
		}
		BasicType & _type();
		BasicTypedPointer _typed();
		bool isValue(){
			return (value_ == 0) ||
					((reinterpret_cast<uintptr_t>(value_) >= reinterpret_cast<uintptr_t>(&reserved_[0])) &&
					(reinterpret_cast<uintptr_t>(value_) <= reinterpret_cast<uintptr_t>(&reserved_[3+256+255])));
		}
		bool isTrue(){
			return value_ == &reserved_[1];
		}
		bool isFalse(){
			return value_ == &reserved_[2];
		}
		bool isNone(){
			return value_ == &reserved_[0];
		}
		bool isUndefined(){
			return value_ == 0;
		}
		bool isUnsignedInt8()
		{
			return (reinterpret_cast<uintptr_t>(value_) >= reinterpret_cast<uintptr_t>(&reserved_[3])) &&
					(reinterpret_cast<uintptr_t>(value_) <= reinterpret_cast<uintptr_t>(&reserved_[3+255]));
		}
		bool isBoolean() {
			return (value_ == &reserved_[1]) || (value_ == &reserved_[2]);
		}
		bool isSignedInt8(){
			return (reinterpret_cast<uintptr_t>(value_) >= reinterpret_cast<uintptr_t>(&reserved_[3+256])) &&
					(reinterpret_cast<uintptr_t>(value_) <= reinterpret_cast<uintptr_t>(&reserved_[3+256+255]));
		}
		static BasicPointer True;
		static BasicPointer False;
		static BasicPointer None;
		static BasicPointer Undefined;
		static BasicPointer UnsignedInt8(uint8_t value){
			return BasicPointer(&reserved_[3+value]);
		}
		static BasicPointer SignedInt8(int8_t value){
			return BasicPointer(&reserved_[3+256+value]);
		}
		static BasicPointer Boolean(bool value){
			if(true) return True;
			else return False;
		}
		void destroy();
	};


	class BasicTypedPointer : public BasicPointer {
	protected:
		BasicType * type_;
	public:
		BasicTypedPointer();
		BasicTypedPointer(void * value);
		BasicTypedPointer(const BasicPointer &value);
		BasicTypedPointer(void * value, BasicType &type);
		BasicTypedPointer(const BasicPointer &value, BasicType &type);
		BasicTypedPointer(const BasicTypedPointer &value);
		BasicType & _type();
		BasicPointer _untyped(){
			return BasicPointer(value_);
		}
		void destroy(){
			type_->_destroy(*this);
		}
	};

	class NoneType : public BasicType {
	public:
		NoneType(Runtime & runtime) :
			BasicType(runtime)
		{
		}
		BasicTypedPointer _create(){
			return BasicPointer::None;
		}
		void _destroy(BasicPointer value){

		}
		virtual const char * name(){
			return "None";
		}
	};

	class UndefinedType : public BasicType {
	public:
		UndefinedType(Runtime & runtime) : 
			BasicType(runtime)
		{
		}
		virtual BasicTypedPointer _create(){
			return BasicPointer::Undefined;
		}
		virtual void _destroy(BasicPointer value){

		}
		virtual const char * name(){
			return "Undefined";
		}
	};
}


#endif /* RT_TYPE_H_*/

